package cn.itsource.system.util;

import cn.hutool.core.lang.ClassScanner;
import cn.hutool.core.util.StrUtil;
import cn.itsource.system.annotation.PermissionAnnotation;
import cn.itsource.system.domain.Permission;
import cn.itsource.system.mapper.PermissionMapper;
import cn.itsource.system.query.PermissionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 自定义类，用来扫描当前项目下面的自定义注解
 */
@Component
public class PermissionScanUtil {

    //扫描指定包
    private String scanPackage="cn.itsource";

    @Autowired
    private PermissionMapper permissionMapper;

    /**
     * 扫描目标类是哪些(扫描当前项目下面所有的@ControLler注新解)
     * 2.扫描这些类下面所有的方法，并且有加@PermissionAnnotation注解的
     * 3.如果方法上面加了此注解，那么我就要判断，数据库里面是否有对应的资源
     * 如果有:修改 如果没有:就新增
     */
    public void scan(){
        //扫描指定包的注解
        Set<Class<?>> classes1 = ClassScanner.scanPackageByAnnotation(scanPackage, RestController.class);
        Set<Class<?>> classes2 = ClassScanner.scanPackageByAnnotation(scanPackage, Controller.class);
        //System.out.println("追风安慰覅");
        //获取所有的权限列表
        List<Permission> permissionList = permissionMapper.selectAll(new PermissionQuery());
        //集合转为map
        Map<String, Permission> map = permissionList.stream().collect(Collectors.toMap(Permission::getSn, p -> p));
        //创建一个空集合，专门来装控制层对应的类型
        Set<Class<?>> classes = new HashSet<>();
        //添加控制器类字节码集合
        classes.addAll(classes1);
        classes.addAll(classes2);
        //循环所有的控制类
        for (Class<?> aClass : classes) {
            //获取控制器中的所有共公方法
            Method[] methods = aClass.getMethods();
            //循环方法
            for (Method method : methods) {
                //获取注解
                PermissionAnnotation annotation = method.getAnnotation(PermissionAnnotation.class);
                //如果方法注解为空，跳过
                if (annotation == null) {
                    continue;
                }
                //获取权限编码
                String sn = annotation.sn();
                //获取地址
                String url = annotation.url();
                //如果url为空，就证明，手动没有填写url，需要程序自己拼接
                if(StrUtil.isBlank(url)){
                    //获取方法上面的url地址
                    url = getRequstMappingUrl(aClass, method);
                }
                //获取请求方式
                String methodType = getMethodType(method);

                //判断map集合中是否包含sn，如果包含，就走修改
                if (map.containsKey(sn)) {
                    Permission permission = map.get(sn);
                    permission.setName(annotation.name());
                    permission.setDescs(annotation.dascs());
                    permission.setUrl(url);
                    permission.setMethodType(methodType);
                    permissionMapper.updateByPrimaryKey(permission);
                } else {
                    Permission permission = new Permission();
                    permission.setName(annotation.name());
                    permission.setDescs(annotation.dascs());
                    permission.setUrl(url);
                    permission.setSn(annotation.sn());
                    permission.setMethodType(methodType);
                    permissionMapper.insert(permission);
                }
            }
        }
    }

    private String getMethodType(Method method) {
        //获取类上的RequestMapping注解
        RequestMapping restController = method.getAnnotation(RequestMapping.class);
        //如果不为空，能接收请求
        if (restController != null) {
            return "";
        }
        //如果不为空
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
           return RequestMethod.POST.toString();
        }

        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping != null) {
            return RequestMethod.GET.toString();
        }


        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            return RequestMethod.DELETE.toString();
        }

        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            return RequestMethod.PUT.toString();
        }


        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            return RequestMethod.PATCH.toString();
        }

        return "";
    }

    private String getRequstMappingUrl(Class<?> aClass, Method method) {
        //获取类上的RequestMapping注解
        RestController restController = aClass.getAnnotation(RestController.class);
        String url="";
        //不为空，证明有注解
        if (restController!=null) {
            //获取类上的ur1地址
            String[] value = new String[]{restController.value()};
            //获取类上的url地址
            String preFixRequest = value[0];
            //获取类上ur1地址是否以/开始
            url = preFixRequest.startsWith("/") ? preFixRequest : ("/" + preFixRequest);
        }
        //如果不为空
        PostMapping postMapping = method.getAnnotation(PostMapping.class);
        if (postMapping != null) {
            String[] value = postMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }

        GetMapping getMapping = method.getAnnotation(GetMapping.class);
        if (getMapping != null) {
            String[] value = getMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }


        DeleteMapping deleteMapping = method.getAnnotation(DeleteMapping.class);
        if (deleteMapping != null) {
            String[] value = deleteMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }

        PutMapping putMapping = method.getAnnotation(PutMapping.class);
        if (putMapping != null) {
            String[] value = putMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }


        PatchMapping patchMapping = method.getAnnotation(PatchMapping.class);
        if (patchMapping != null) {
            String[] value = patchMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }

        RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
        if (requestMapping != null) {
            String[] value = requestMapping.value();
            if (value.length==0) {
                return  url;
            }else {
                String suffixRequstMapping = value[0];
                url = suffixRequstMapping.startsWith("/")?(url+suffixRequstMapping):(url+"/"+suffixRequstMapping);
                return url;
            }
        }

        return "";
    }
}

